Posts

Post marked as solved
1 Replies
I found it: #import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
Post marked as solved
1 Replies
If what you need to do is add a white border around and image, here's some code -(NSImage *)addBorderToImage: (NSImage *)oldImage width: (CGFloat)w; { NSSize size; NSRect iRect; NSImage *newImage; size = oldImage.size; iRect.origin.x = w; iRect.origin.y = w; iRect.size = size; size.width += 2 * w; size.height += 2 * w; newImage = [[NSImage alloc] initWithSize: size]; [newImage lockFocus]; [[NSColor whiteColor] drawSwatchInRect: NSMakeRect( 0 , 0 , size.width, size.height)]; [oldImage drawInRect: iRect]; [newImage unlockFocus]; return newImage; } code-block
Post marked as solved
4 Replies
I found a work around to the problem. In the example code below, in response to a color change the action message, newColor:, changes the color of the image and calls the button's setImage: message. This actually is the same NSImage object already in the Button. In this case the API ignores the setNeedsDisplay message. If a new NSImage object is created, as in the line commented out, and sent to the Button, the Button is redrawn with the new image. I still think it is a bug that the in the first instance the setNeedsDisplay message is ignored. // AppDelegate.m // TestUI // // Created by Bruce D MacKenzie on 11/20/22. // #import "AppDelegate.h" @interface AppDelegate () { } @property (strong) IBOutlet NSWindow *window; @property (assign) IBOutlet NSButton *theButton; @end @implementation AppDelegate { NSImage *image; } @synthesize theButton; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application } - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } -(void)awakeFromNib { image = [[NSImage alloc] initWithSize: NSMakeSize( 32 , 32 )]; [image lockFocus]; [[NSColor redColor] drawSwatchInRect: NSMakeRect(0, 0, 32, 32)]; [image unlockFocus]; [[self theButton] setImage: image]; } - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app { return YES; } -(IBAction)newColor: (NSColorWell *)sender { NSColor *newColor; newColor = [sender color]; // image = [[NSImage alloc] initWithSize: NSMakeSize( 32 , 32 )]; [image lockFocus]; [newColor drawSwatchInRect: NSMakeRect( 0, 0, 32, 32)]; [image unlockFocus]; [[self theButton] setImage: image]; [[self theButton] setNeedsDisplay: YES]; } code-block
Post marked as solved
2 Replies
I found the problem. Yesterday when entering an accent, á, I inadvertently turned on Mouse Keys which reassigns the numeric keyboard.
Post marked as solved
2 Replies
Included in the sample code project MigratingOpenGLCodeToMetal is the file AAPLMathUtilities. This file contains two functions for creating projection matrixes: /// Constructs a symmetric perspective Projection Matrix /// from left-handed Eye Coordinates to left-handed Clip Coordinates, /// with a vertical viewing angle of fovyRadians, the specified aspect ratio, /// and the provided absolute near and far Z distances from the eye. matrix_float4x4 AAPL_SIMD_OVERLOAD matrix_perspective_left_hand(float fovyRadians, float aspect, float nearZ, float farZ); /// Constructs a symmetric perspective Projection Matrix /// from right-handed Eye Coordinates to left-handed Clip Coordinates, /// with a vertical viewing angle of fovyRadians, the specified aspect ratio, /// and the provided absolute near and far Z distances from the eye. matrix_float4x4 AAPL_SIMD_OVERLOAD matrix_perspective_right_hand(float fovyRadians, float aspect, float nearZ, float farZ); So, I guess one can define the geometry of one's objects using either a right hand or a left hand coordinate system and have it display properly depending on which of these two one uses to construct the projection matrix. This is good. I think I understand things much better now.
Post not yet marked as solved
2 Replies
I have placed a little Xcode project on github that renders to an off screen texture to do mouse picking.
Post marked as solved
3 Replies
Rather than have dispatch_apply() run the loop I have replaced the above with repeated calls to dispatch_async() to avoid the problem. The following code works like a hose. - (void)searchTreeBranches { int n; RBK_Turn turn; // load up the processor cores for ( n = 0 ; n < turnsMax; n++) { turn = turns[n]; dispatch_async( myDispatchQueue, ^( void ) { ••• }); } }
Post marked as solved
3 Replies
I think I have a clearer picture of what the problem is. The code block is an IDA (Iterative Deepening Algorithm) search in the Cayley graph of the Rubik's Cube group for a solution to a cube position. For the first few iterations the code block returns almost immediately. As the search goes deeper the times increase exponentially. The problem is that GCD profiles the block based on the early iterations and decides it would be more efficiently run serially. So, when the search reaches a deeper level where parallel processing gives a huge performance increase GCD continues to run the tasks one at a time. How can one preempt that profiling?
Post marked as solved
3 Replies
Using the more explicit method: unarchivedDictionaryWithKeysOfClasses:objectsOfClasses:fromData:error: eliminates all the problems. The following code executes with no errors. -(void)test: (NSString *)input { NSDictionary *source, *destination; NSSet *classes; NSMutableData *mData1, *mData2; NSData *table1, *table2, *archive; NSError *error; @autoreleasepool { mData1 = [NSMutableData dataWithData: edgeTableC3v]; mData2 = [NSMutableData dataWithData: cornerTableC3v]; table1 = mData1; table2 = mData2; source = [NSDictionary dictionaryWithObjectsAndKeys: input, @"input", table1, @"edge table", table2, @"corner table", nil]; archive = [NSKeyedArchiver archivedDataWithRootObject: source requiringSecureCoding: YES error: &error]; if( error != nil ) { [self report: [NSString stringWithFormat: @"\nError creating archive\n\t%@", [error localizedFailureReason]]]; } else { classes = [NSSet setWithObjects: [NSData class], [NSString class], nil]; destination = [NSKeyedUnarchiver unarchivedDictionaryWithKeysOfClasses: [NSSet setWithObject: [NSString class]] objectsOfClasses: classes fromData: archive error: &error]; if( error != nil) { [self report: [NSString stringWithFormat: @"\nError reading archive\n\t%@", [error localizedFailureReason]]]; } else [self report: [NSString stringWithFormat: @"\nNo Error\n%@", [destination description]]]; } [self reportDone]; } } OUTPUT No Error { "corner table" = {length = 2449440, bytes = 0x88a40000 e0970000 98c40000 48b70000 ... f3b00000 85a40000 }; "edge table" = {length = 145152, bytes = 0x00000000 00000000 140b0000 250a0000 ... 99090000 bf080000 }; input = Parameters; } Note that I archived NSMutableData objects and they were unarchived with no error. The runtime doesn't send any warnings when unarchiving.
Post marked as solved
3 Replies
Replied In Random Numbers
I found the docs I needed: [https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc). The core foundation security services api contains the appropriate system call. The modern implementation of the above would be: -(uint64)random64 { uint64_t value = 0; uint8 randomByte; int i, err; for (i = 0 ; i < sizeof(value); i++) { value <<= 8; err = SecRandomCopyBytes( kSecRandomDefault , 1 , &randomByte ); value |= randomByte; } return value; }
Post marked as solved
3 Replies
pruneTableP2 is an NSData object holding a 200+mbyte table. The first time the user launches the program the table must be calculated and that routine uses an NSMutableData object for that. This is archived to the users home directory to be loaded from disk thereafter. So, although typed as NSData, pruneTableP2 actually is a pointer to an NSMutableData object when it is archived. Sometime after the app was written stricter type checking was added to NSKeyedUnarchiver and the code broke. The fix is to use a pure NSData object rather than its subclass to create the archive. It is disturbing that even then the runtime sends out these warnings: Multiline 2021-11-04 08:24:55.954653-0500 Cube Console[1366:19975] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSData' (0x1dda3e558) [/System/Library/Frameworks/CoreFoundation.framework]' for key 'NS.objects', even though it was not explicitly included in the client allowed classes set: '{( "'NSDictionary' (0x1dda3e5d0) [/System/Library/Frameworks/CoreFoundation.framework]" )}'. This will be disallowed in the future . 2021-11-04 08:24:55.955503-0500 Cube Console[1366:19975] [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSString' (0x1dda6c848) [/System/Library/Frameworks/Foundation.framework]' for key 'NS.keys', even though it was not explicitly included in the client allowed classes set: '{( "'NSDictionary' (0x1dda3e5d0) [/System/Library/Frameworks/CoreFoundation.framework]" )}'. This will be disallowed in the future. BlockQuote code-block
Post not yet marked as solved
2 Replies
On reading my post I realized that the data in the C array is in row major order. The row index changes fastest and that is the right most index in a C array. I feel stupid.
Post not yet marked as solved
1 Replies
After over a week of wandering around in the dark, I discovered how convert the coordinates. The input shadowSpacePosition is in Metal Normalized Coordinates: x and y -1 to 1, z 0 to 1 with the origin at the center of the drawable. When this is stored in the depth texture it is converted to texture coordinates: x,y and z 0 to 1 with the origin on the bottom-left. So to read the proper depth in the depth texture the code is: &#9;&#9; constexpr sampler shadowSampler(coord::normalized, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; filter::linear, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; address::clamp_to_zero, &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; compare_func:: less); &#9;&#9;shadowPosition = in.shadowSpacePosition.xyz; &#9;&#9;shadowPosition.y *= -1; &#9;&#9;shadowPosition.xy += 1.0; &#9;&#9;shadowPosition.xy /= 2; &#9;&#9;cmp = shadowTexture.sample_compare(shadowSampler, shadowPosition.xy , shadowPosition.z); &#9; if(cmp < 0.1) &#9;&#9;&#9; isShadow = true; &#9;&#9;else &#9;&#9;&#9;&#9;isShadow = false;
Post not yet marked as solved
6 Replies
No, it's what you have to do in OpenGl. The problem is determining what object in a 3D rendered scene is under the mouse. This is "picking" or "hit testing". I use the standard tecnique of rendering the scene off screen giving each object one is interested in a unique "color". One then reads the pixels under the mouse to determine which if any of the objects is hit.Looking at my code, what I have done is divide the view into a 100x100 grid of rectangles. I then scan through and any rectangle inside a hit triangle gets added to my array of cursor rectangles. I now am working on scanning through this list and merging adjacent rectangles. I should be able to significantly reduce the number of cursor rectangles required. The thing is I shouldn't have to do this. Power to the developer. If I want to have three or four hundred cursor rectangles the API shouldn't prevent me.
Post not yet marked as solved
6 Replies
Yes, to get it to work as it stands now I'm going to have reduce the number of rectangles. I may be able to merge some of them into larger rectangles. I'll have to dig into the code.The thing is the geometry of the hit triangles is not well defined. The original geometry has been rotated around and projected onto the display in OpenGL. Many are not visible and have been culled. In the present code I determine where they are by reading pixles out of the frame buffer.